﻿// *----------------------------------------------------------------
// Copyright (C) 2017 通通优品
// 版权所有。
// 
// 类名：DapperDbContextProvider.cs
// 功能描述：TongTongMall.Dapper
// 
// Create User：jym 2017/02/09
// 
// Edit User：UserName,EditTime
// Describe：Describe
// ----------------------------------------------------------------*/
using Castle.Core.Logging;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TongTongMall.Dapper.DapperExtensions;
using TongTongMall.Dapper.Repository;
using TongTongMall.Dapper.Uow;
using TongTongMall.Domain.Uow;

namespace TongTongMall.Dapper
{
    public class DapperDbContextProvider<TDatabase> : IDbContextProvider<TDatabase>
     where TDatabase : IDatabase
    {
        public TDatabase DbContext { get; private set; }

        public ILogger Logger { get; set; } = NullLogger.Instance;

        public IDbProviderFactory _dbProviderFactory { get; private set; }
        
        public string ConnectionString { get; private set; }

        private readonly ICurrentUnitOfWorkProvider _currentUnitOfWorkProvider;

        public DapperDbContextProvider(TDatabase dbContext, IDbProviderFactory dbProviderFactory, ICurrentUnitOfWorkProvider currentUnitOfWorkProvider)
        {
            DbContext = dbContext;
            if (dbProviderFactory == null) throw new ArgumentNullException("dbProviderFactory");
            _dbProviderFactory = dbProviderFactory;
            ConnectionString = dbProviderFactory.ConnectionString;
            _currentUnitOfWorkProvider = currentUnitOfWorkProvider;
        }

        public TDatabase GetDbContext()
        {
            var connecionWrapper = GetOpenConnection();
            DbContext.SetConnection(connecionWrapper.Connection);
            return DbContext;
        }

        /// <summary>
        /// 获取一个始终打开的数据库连接
        /// </summary>
        /// <returns></returns>
        protected DatabaseConnectionWrapper GetOpenConnection()
        {
            DatabaseConnectionWrapper connection = TransactionScopeConnections<TDatabase>.GetConnection(this);
            var unitOfWork = _currentUnitOfWorkProvider.Current as DapperUnitOfWork;
            var connectionWrapper = connection ?? unitOfWork.GetOrSetDatabaseConnectionWrapper(() =>
            {
                return new DatabaseConnectionWrapper(GetNewOpenConnection());
            });
            //if (connectionWrapper != null && connectionWrapper.Connection.State == ConnectionState.Closed)
            //{
            //    connectionWrapper.Connection.Open();
            //}
            return connectionWrapper;
        }

        /// <summary>
        /// 获取一个新的连接
        /// </summary>
        /// <returns></returns>
        internal DbConnection GetNewOpenConnection(bool isOpen=false)
        {
            DbConnection connection = null;
            try
            {
                connection = CreateConnection();
                if (isOpen) connection.Open();
            }
            catch
            {
                if (connection != null && connection.State == ConnectionState.Open)
                    connection.Close();
                Logger.Error("open database is error");
                throw;
            }
            return connection;
        }

        private DbConnection CreateConnection()
        {
            DbConnection newConnection = _dbProviderFactory.DbFactory.CreateConnection();
            newConnection.ConnectionString = _dbProviderFactory.ConnectionString;
            return newConnection;
        }

        //public string GetCurrentConnectionListKeys()
        //{
        //    return TransactionScopeConnections<TDatabase>.ConnectionListKey;
        //}

        //public void DisposedConnections()
        //{
        //    TransactionScopeConnections<TDatabase>.OnConnectionDisposed();
        //}
    }
}
 